package net.toby200.canalbuddy.notices;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;

import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.json.gson.GsonFactory;

import net.toby200.canalbuddy.notices.model.Location;
import net.toby200.canalbuddy.notices.model.Notice;
import net.toby200.canalstoppages.stoppages.Stoppages;
import net.toby200.canalstoppages.stoppages.model.NoticeCollection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by toby on 20/06/2014.
 */
public class NoticesManager extends Fragment {

    public static interface TaskCallbacks {
        void onPreExecute();
        void onPostExecute(Collection<Notice> notices);
    }

    private final Logger LOG = Logger.getLogger(NoticesManager.class.getName());

    private Date lastUpdateTime = new Date(0);
    Map<String, Notice> notices = new HashMap<String, Notice>();

    private TaskCallbacks callbacks;

    public NoticesManager() {
        LOG.info("Started NoticesManager instance");
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        LOG.info("NoticesManager.onAttach()");
        callbacks = (TaskCallbacks) activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        LOG.info("NoticesManager.onDetach()");
        callbacks = null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        LOG.info("NoticesManager.onDestroy()");
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LOG.info("NoticesManager.onCreate()");
        // Retain this fragment across configuration changes.
        setRetainInstance(true);

    }


    public void refreshNotices(Context context) {
        try {
            new NoticeFetcher(context).execute();
        } catch (Exception e) {
            LOG.log(Level.SEVERE, "Error getting stoppages", e);
        }
    }

    public Collection<Notice> getNotices() {
        return notices.values();
    }

    public Notice getNotice(String title) {
        return notices.get(title);
    }

    public void loadNotices(Context context) {
        if (notices != null && notices.size() > 0) {
            callbacks.onPostExecute(notices.values());
        } else {
            refreshNotices(context);
        }
    }

    private class NoticeFetcher extends AsyncTask<Void, Void,  Collection<Notice>> implements TaskCallbacks {
        Context context;


        public NoticeFetcher(Context context) {
            this.context = context;
        }

        public void onPreExecute(){
            super.onPreExecute();
            if (callbacks != null) {
                callbacks.onPreExecute();
            }
        }

        protected  Collection<Notice> doInBackground(Void... unused) {

            try {
                LOG.info("Fetching notices in background thread");
                Stoppages.Builder builder = new Stoppages.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), null);
                builder.setApplicationName("CanalBuddyClient");
                Stoppages service = builder.build();
                NoticeCollection noticeCol = service.getStoppages().execute();
                notices.clear();
                for (net.toby200.canalstoppages.stoppages.model.Notice notice : noticeCol.getItems()) {
                    // convert from API notice to internal notice that doesn't extend GenericJson
                    Location startLoc = notice.getStartLoc() != null ?  new Location(notice.getStartLoc().getLat(), notice.getStartLoc().getLng()) : null;
                    Location endLoc = notice.getEndLoc() != null ? new Location(notice.getEndLoc().getLat(), notice.getEndLoc().getLng()) : null;
                    Notice androidNotice = new Notice(notice.getId(), notice.getTitle(), notice.getWaterway(), notice.getFromDate(), notice.getToDate(),
                            notice.getType(), notice.getDescription(), notice.getLocationDetail(), startLoc, endLoc, notice.getLastUpdated());
                    LOG.finest(androidNotice.toString());
                    notices.put(notice.getTitle(), androidNotice);
                }
                NoticesManager.this.lastUpdateTime = new Date();
            } catch (Exception e) {
                LOG.log(Level.SEVERE, "Could not retrieve notices", e);
            }
            return notices != null ? notices.values() : new ArrayList<Notice>();
        }

        public void onPostExecute(Collection<Notice> notices) {
            super.onPostExecute(notices);
            callbacks.onPostExecute(notices);
        }



    }

}
